skuSelect
<template>
    <div>
        <el-button type="primary" @click="handleAddGoods">添加商品</el-button>
        <!-- <AddDialog :is-multi="false"></AddDialog> -->
        <el-dialog
            class="good_spec_template_dialog"
            title="添加商品"
            v-model="visible"
            width="80%"
            @close="closedCallback">
            <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
                <el-form-item label="商品类型" prop="goods">
                    <el-radio-group
                        v-if="visible"
                        class="custom-group"
                        v-model="form.goodsType"
                        @change="goodsTypeChange">
                        <div class="radio-item" v-for="item in goodsTypes" :key="item.label">
                            <el-radio :label="item.label">{{ item.name }}</el-radio>
                            <ZwChooseCoupon
                                @handle-confirm="getCouponData"
                                :value="skuSelect[0]?.couponId"
                                :isShop="true"
                                v-if="item.label == 2 && form.goodsType == 2">
                                <template #btn>
                                    <el-button type="primary"> 选择优惠券 </el-button>
                                </template>
                            </ZwChooseCoupon>
                            <ChooseDraw
                                v-if="item.label == 3 && form.goodsType == 3"
                                :value="skuSelect[0] || {}"
                                @handle-confirm="getDrawData">
                                <template #btn>
                                    <el-button type="primary"> 选择抽奖活动 </el-button>
                                </template>
                            </ChooseDraw>
                            <ChoosePointGood
                                v-if="item.label == 1 && form.goodsType == 1"
                                :is-multi="false"
                                :value="selectData"
                                :searchParams="{ filter: 'points' }"
                                @handle-confirm="getGoodData">
                                <template #btn>
                                    <el-button type="primary"> 选择商品 </el-button>
                                </template>
                            </ChoosePointGood>
                            <!-- todo:抽奖机会列表显示来源店铺 -->
                            <!-- todo:商品列表显示来源店铺 -->
                            <!-- todo:优惠券列表显示来源店铺 -->
                        </div>
                    </el-radio-group>
                    <!-- todo:只有商品展示 -->
                    <el-table
                        class="custom-table-fit"
                        style="margin-top: 16px"
                        v-if="selectData && selectData.skuInfo && form.goodsType == 1"
                        :data="[{}]">
                        <el-table-column
                            v-for="{ prop, ...rest } in tableColumns"
                            :key="prop"
                            :prop="prop"
                            v-bind="rest">
                            <template #default>
                                <el-popconfirm
                                    v-if="prop === 'operation'"
                                    placement="top"
                                    width="250px"
                                    title="确定要删除吗？"
                                    @confirm="handleRemove(row)"
                                    confirm-button-text="确定"
                                    cancel-button-text="取消">
                                    <template #reference>
                                        <el-button v-if="prop === 'operation'" size="small">删除</el-button>
                                    </template>
                                </el-popconfirm>
                                <template v-else>
                                    <div class="custom-goods-name" v-if="prop === 'goodsName'">
                                        <el-image
                                            style="width: 40px; height: 40px; min-width: 40px; margin-right: 4px"
                                            :src="selectData?.materialSrc?.[0]?.materialSrc"
                                            fit="fill"></el-image>
                                        <el-tooltip effect="dark" :content="selectData.goodsName" placement="top">
                                            <span class="custom-goods-name-span">{{ selectData.goodsName }}</span>
                                        </el-tooltip>
                                    </div>
                                    <span v-if="!['goodsName'].includes(prop)">
                                        {{ selectData[prop] }}
                                    </span>
                                </template>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-form-item>
                <el-form-item label="兑换价" prop="skuSelect">
                    <el-radio-group
                        class="custom-group"
                        v-model="form.pointsConsumerType"
                        @change="pointsConsumerChange">
                        <!-- 商城商品显示 -->
                        <div class="radio-item">
                            <el-radio v-if="form.goodsType == 1" :label="1">
                                使用统一兑换比例：{{ query.points }}积分={{ query.rmb }}元</el-radio
                            >
                        </div>
                        <!-- 抽奖，优惠券，商城商品显示 -->
                        <div class="radio-item">
                            <el-radio :label="2">自定义兑换价</el-radio>
                        </div>
                    </el-radio-group>
                    <!-- 商城商品 -->
                    <el-table
                        class="custom-table-fit"
                        v-if="form.goodsType == 1"
                        ref="multipleTableRef"
                        @selection-change="handleSelectionChange"
                        :data="selectData?.skuInfo || []">
                        <el-table-column type="selection" width="55" />
                        <el-table-column
                            v-for="{ prop, ...rest } in skuTableColumnsCopy"
                            :key="prop"
                            :prop="prop"
                            v-bind="rest">
                            <template #default="{ row }">
                                <template v-if="prop === 'specAttr'">
                                    {{ row?.specAttr?.map(item => item.attributeValue)?.join('；') }}
                                </template>
                                <template v-if="prop === 'skuPrice'">
                                    {{ `￥${row.skuPrice / 100}` }}
                                </template>
                                <template v-if="prop === 'points'">
                                    <template v-if="form.pointsConsumerType == 1">
                                        {{ (row?.skuPrice * (query.points / query.rmb)) / 100 }}积分
                                    </template>
                                    <!-- todo:自定义兑换价 -->
                                    <template v-if="form.pointsConsumerType == 2">
                                        <el-input-number
                                            v-model="row.money"
                                            class="width-60"
                                            :min="0"
                                            :max="99999999"
                                            :precision="2"
                                            :controls="false" />
                                        元+
                                        <el-input-number
                                            v-model="row.points"
                                            class="width-60"
                                            :min="1"
                                            :max="99999999"
                                            :precision="0"
                                            :controls="false" />
                                        积分
                                    </template>
                                </template>
                            </template>
                        </el-table-column>
                        <template #empty> 请先选择商品 </template>
                    </el-table>
                    <!-- 抽奖 -->
                    <el-table class="custom-table-fit" v-if="form.goodsType == 3" :data="skuSelect">
                        <el-table-column
                            v-for="{ prop, ...rest } in drawTableColumns"
                            :key="prop"
                            :prop="prop"
                            v-bind="rest">
                            <template #default="{ row }">
                                <!-- todo:自定义兑换价 -->
                                <template v-if="prop === 'points'">
                                    <el-input-number
                                        v-model="row.money"
                                        class="width-60"
                                        :max="99999999"
                                        :min="0"
                                        :precision="2"
                                        :controls="false" />
                                    元+
                                    <el-input-number
                                        v-model="row.points"
                                        class="width-60"
                                        :max="99999999"
                                        :min="1"
                                        :precision="0"
                                        :controls="false" />
                                    积分
                                </template>
                                <!-- todo:删除 -->
                                <el-popconfirm
                                    v-if="prop === 'operation'"
                                    placement="top"
                                    width="250px"
                                    title="确定要删除吗？"
                                    @confirm="handleRemoveSelected(row)"
                                    confirm-button-text="确定"
                                    cancel-button-text="取消">
                                    <template #reference>
                                        <el-button v-if="prop === 'operation'" size="small">删除</el-button>
                                    </template>
                                </el-popconfirm>
                            </template>
                        </el-table-column>
                        <template #empty> 请先选择抽奖机会 </template>
                    </el-table>
                    <!-- 优惠卷 -->
                    <el-table class="custom-table-fit" v-if="form.goodsType == 2" :data="skuSelect">
                        <el-table-column
                            v-for="{ prop, ...rest } in couponTableColumns"
                            :key="prop"
                            :prop="prop"
                            v-bind="rest">
                            <template #default="{ row }">
                                <!-- todo:自定义兑换价 -->
                                <template v-if="prop === 'points'">
                                    <el-input-number
                                        v-model="row.money"
                                        class="width-60"
                                        :max="99999999"
                                        :min="0"
                                        :precision="2"
                                        :controls="false" />
                                    元 +
                                    <el-input-number
                                        v-model="row.points"
                                        class="width-60"
                                        :max="99999999"
                                        :min="1"
                                        :precision="0"
                                        :controls="false" />
                                    积分
                                </template>
                                <!-- todo:删除 -->
                                <el-popconfirm
                                    v-if="prop === 'operation'"
                                    placement="top"
                                    width="250px"
                                    title="确定要删除吗？"
                                    @confirm="handleRemoveSelected(row)"
                                    confirm-button-text="确定"
                                    cancel-button-text="取消">
                                    <template #reference>
                                        <el-button v-if="prop === 'operation'" size="small">删除</el-button>
                                    </template>
                                </el-popconfirm>
                            </template>
                        </el-table-column>
                        <template #empty> 请先选择优惠券 </template>
                    </el-table>
                </el-form-item>
                <!-- 优惠券，抽奖显示 -->
                <el-form-item label="商品名称" prop="goodsName" v-if="[2, 3].includes(form.goodsType)">
                    <el-input
                        v-model.trim="form.goodsName"
                        class="good-name-input"
                        maxlength="50"
                        show-word-limit></el-input>
                </el-form-item>
                <!-- 抽奖显示 -->
                <el-form-item label="总兑换数" prop="totalExchange" v-if="form.goodsType == 3">
                    <el-radio-group v-model="form.totalUnlimit" @change="handleTotalChange">
                        <el-radio :label="1">无限制</el-radio>
                        <el-radio :label="0">一共</el-radio>
                    </el-radio-group>
                    <el-input-number
                        :disabled="form.totalUnlimit == 1"
                        v-model="form.totalExchange"
                        class="custom-number-small"
                        :min="0"
                        :max="99999999"
                        :precision="0"
                        :controls="false" />件
                </el-form-item>
                <el-form-item label="每单兑换数量" prop="limit">
                    <el-radio-group v-model="radioVal" @change="handleLimitChange">
                        <el-radio :label="1">无限制</el-radio>
                        <el-radio :label="2">最多</el-radio>
                    </el-radio-group>
                    <el-input-number
                        :disabled="radioVal == 1"
                        v-model="form.limit"
                        class="custom-number-small"
                        :min="0"
                        :max="99999999"
                        :precision="0"
                        :controls="false" />件
                </el-form-item>
            </el-form>
            <template #footer>
                <div style="flex: auto">
                    <el-button plain @click="handleVisible(false)">取消</el-button>
                    <el-button type="primary" @click="handleConfirm">确认</el-button>
                </div>
            </template>
        </el-dialog>
        <!-- 弹窗 -->
    </div>
</template>

<script setup>
import { ref, reactive, computed, unref, nextTick } from 'vue';
import { cloneDeep } from '@/commons/utils';
import { ElMessage } from 'element-plus';
import request from '@/request';
import ChooseDraw from './chooseDraw.vue';
import ChoosePointGood from './choosePointGood.vue';
import { debounce } from 'lodash';

const couponIconUrl = location.origin + '/imgs/coupon-good-default.png';
const drawIconUrl = location.origin + '/imgs/draw-good-default.png';

const props = defineProps({
    query: {
        type: Object,
        default: () => {}
    }
});

const emit = defineEmits(['handle-confirm']);

const formRef = ref();

let visible = ref(false);
let radioVal = ref(1);
const form = reactive({
    shopId: '',
    limit: null,
    totalUnlimit: 1,
    totalExchange: null,
    goodsName: null, // 商品名称
    goodsImg: null, // 商品图片，只有优惠券和抽奖机会有
    goodsType: 2, // 商品类型
    pointsConsumerType: 2 // 兑换价类型
});
const formClone = cloneDeep(form);
const multipleTableRef = ref();

let selectData = reactive({});
const goodsTypes = [
    { name: '优惠券', label: 2 },
    { name: '抽奖机会', label: 3 },
    { name: '商城商品', label: 1 }
];
// 优惠券和抽奖表格
const tableColumns = reactive([
    { label: '商品信息', prop: 'goodsName' },
    { label: '来源店铺', prop: 'shopName' },
    { label: '操作', prop: 'operation', width: '100' }
]);
const skuTableColumns = reactive([
    { label: '规格信息', prop: 'specAttr', showOverflowTooltip: true },
    { label: '库存', prop: 'skuStock' },
    { label: '价格（元）', prop: 'skuPrice' }
]);
const skuTableColumnsCopy = computed(() => {
    const cols = cloneDeep(skuTableColumns);
    cols.push({ label: '兑换价', prop: 'points', width: form.pointsConsumerType == 1 ? '' : '250' });
    return cols;
});
const couponTableColumns = reactive([
    { label: '优惠券名称', prop: 'couponName', showOverflowTooltip: true },
    { label: '库存', prop: 'restNumber' },
    { label: '来源店铺', prop: 'shopName' },
    { label: '兑换价', prop: 'points', width: '250' },
    { label: '操作', prop: 'operation', width: '100' }
]);
const drawTableColumns = reactive([
    { label: '抽奖活动名称', prop: 'activityName', showOverflowTooltip: true },
    { label: '来源店铺', prop: 'shopName' },
    { label: '兑换价', prop: 'points', width: '250' },
    { label: '操作', prop: 'operation', width: '100' }
]);
let skuSelect = reactive([]);
// const checkGood = (rule, val, callback) => {
//     if (form.goodsType == 2) {
//         return callback('请选择优惠券');
//     }
//     if (form.goodsType == 3) {
//         // todo:兑换价和积分
//         return callback('请选择抽奖活动');
//     }
//     if (!selectData?.skuInfo || !selectData?.skuInfo?.length) {
//         return callback('请选择商品');
//     }
//     callback();
// };
const checkSelect = (rule, val, callback) => {
    if (!skuSelect || !skuSelect.length) {
        // 优惠券
        if (form.goodsType == 2) {
            return callback('请选择优惠券');
        }
        // 抽奖活动
        if (form.goodsType == 3) {
            return callback('请选择抽奖活动');
        }
        return callback('请选择商品');
    }
    if (form.pointsConsumerType == 2) {
        const isEmpty = skuSelect.some(
            item => [null, undefined].includes(item.points) || [null, undefined].includes(item.money)
        );
        if (isEmpty) {
            return callback('请填写兑换价');
        }
        const isGreater = skuSelect.some(item => item.money > item.skuPrice / 100);
        if (isGreater) {
            return callback('兑换价现金值不能大于销售价格');
        }
    }
    callback();
};
const checkLimit = (rule, val, callback) => {
    if (radioVal.value == 2 && !val) {
        return callback('每单兑换数量必须是正整数');
    }
    callback();
};
const checkTotal = (rule, val, callback) => {
    if (form.totalUnlimit == 0 && !val) {
        return callback('每单兑换数量必须是正整数');
    }
    callback();
};
const checkPrice = (rule, val, callback) => {
    if (!val) {
        return callback('不能为空');
    }
    callback();
};
const checkPoint = (rule, val, callback) => {
    if (!val || val <= 0) {
        return callback('必须是正整数');
    }
    callback();
};
const checkPointRule = row => {
    const fn = (rule, val, callback) => {
        if (form.goodsType == 1 && form.pointsConsumerType == 1) {
            callback();
        }
        if (row.points === null && row.money === null) {
            callback('请填写兑换价');
        }
        callback();
    };
    return fn;
};
const rules = {
    // goods: [{ required: true, trigger: 'blur', validator: checkGood }],
    skuSelect: [{ required: false, trigger: 'blur', validator: checkSelect }],
    goodsName: [
        { required: true, message: '请输入商品名称', trigger: 'blur' },
        { max: 50, message: '最长不超过50个字', trigger: 'blur' }
    ],
    limit: [{ required: true, trigger: 'blur', validator: checkLimit }],
    totalExchange: [{ required: true, trigger: 'blur', validator: checkTotal }]
};

// todo:单个检验
const pointRules = [{ required: true, trigger: 'blur', validator: checkPointRule }];

// todo:不同判定computed rules

const getGoodData = data => {
    // 选择
    skuSelect.length = 0;
    Object.assign(selectData, data);
    nextTick(() => {
        multipleTableRef.value?.clearSelection();
        selectData?.skuInfo.forEach(row => {
            multipleTableRef.value?.toggleRowSelection(row, undefined);
        });
        clearValidate('skuSelect');
    });
};
const getCouponData = data => {
    skuSelect.length = 0;
    const { couponName, restNumber, id: couponId, shopName, shopId } = data;
    form.goodsName = couponName;
    skuSelect.push({
        couponName,
        restNumber,
        shopName,
        shopId,
        couponId, //优惠券ID
        points: null, //对应的积分
        money: null //对应的钱数
    });
    clearValidate('skuSelect');
};
const getDrawData = data => {
    skuSelect.length = 0;
    const { activityName, id: activityId, shopName, shopId } = data;
    form.goodsName = activityName;
    skuSelect.push({
        activityName,
        shopName,
        shopId,
        activityId, // 抽奖id
        points: null, // 对应的积分
        money: null // 对应的钱数
    });
    clearValidate('skuSelect');
};

const clearValidate = field => {
    unref(formRef).clearValidate(field);
};
const validateField = field => {
    unref(formRef).validateField(field);
};

const handleAddGoods = () => {
    // if (!props.query?.points) {
    //     ElMessage({
    //         type: 'error',
    //         message: '请先去积分规则中设置积分消耗'
    //     });
    //     return;
    // }
    handleVisible(true);
};
const handleVisible = (isVisible = false) => {
    visible.value = isVisible;
};
const resetSelected = () => {
    const keys = Object.keys(selectData);
    let obj = {};
    keys.forEach(item => {
        obj[item] = null;
    });
    Object.assign(selectData, obj);
    skuSelect.length = 0;
};
const closedCallback = () => {
    // 关闭后的回调
    resetSelected();
    radioVal.value = 1;
    Object.assign(form, cloneDeep(formClone));
    formRef.value.resetFields();
    multipleTableRef?.value?.clearSelection();
};

const goodsTypeChange = val => {
    resetSelected();
    clearValidate('skuSelect');
    if (val !== 1) {
        form.pointsConsumerType = 2;
    } else {
        form.goodsName = null;
        form.pointsConsumerType = 1;
    }
};

const pointsConsumerChange = val => {
    nextTick(() => {
        multipleTableRef.value?.clearSelection();
        selectData?.skuInfo?.forEach(row => {
            multipleTableRef.value?.toggleRowSelection(row, undefined);
        });
    });
    if (val != 1) {
        return;
    }
    clearValidate('skuSelect');
    skuSelect.forEach(item => {
        item.money = null;
        item.points = null;
    });
    selectData?.skuInfo.forEach(item => {
        item.money = null;
        item.points = null;
    });
};

const handleRemove = () => {
    multipleTableRef.value?.clearSelection();
    const keys = Object.keys(selectData);
    let obj = {};
    keys.forEach(item => {
        obj[item] = null;
    });
    Object.assign(selectData, obj);
};

const handleRemoveSelected = () => {
    skuSelect.length = 0;
};

const handleSelectionChange = val => {
    skuSelect.length = 0;
    const arr = (val || []).map(item => {
        // item.money = item.money || null;
        return item;
    });
    skuSelect.push(...arr);
    clearValidate('skuSelect');
};

const handleLimitChange = val => {
    form.limit = null;
    clearValidate('limit');
};

const handleTotalChange = val => {
    form.totalExchange = null;
    clearValidate('totalExchange');
};

const handleConfirm = debounce(async () => {
    if (!unref(formRef)) return;
    await unref(formRef).validate(async (valid, fields) => {
        if (valid) {
            // 不同商品不同积分
            const { limit, totalExchange, totalUnlimit, ...rest } = cloneDeep(form);
            // 抽奖
            const goodsList =
                form.goodsType == 1
                    ? [
                          {
                              goodId: selectData?.id,
                              skuList: skuSelect?.map(
                                  ({ id: skuId, skuPrice, points: pointsCopy, money: moneyCopy }) => {
                                      // 统一兑换比例和自定义兑换不同
                                      const points =
                                          form.pointsConsumerType == 1
                                              ? Math.round(skuPrice * (props.query.points / props.query.rmb))
                                              : pointsCopy * 100;
                                      const item = {
                                          skuId,
                                          points,
                                          money: Math.round(moneyCopy * 100)
                                      };
                                      return item;
                                  }
                              )
                          }
                      ]
                    : null;
            // 优惠券和抽奖
            const { couponId, points: pointsCopy, money: moneyCopy, activityId } = skuSelect?.[0] || {};
            const couponList =
                form.goodsType == 2
                    ? {
                          couponId,
                          points: pointsCopy * 100,
                          money: Math.round(moneyCopy * 100)
                      }
                    : null;
            const luckDraw =
                form.goodsType == 3
                    ? {
                          activityId,
                          points: pointsCopy * 100,
                          money: Math.round(moneyCopy * 100)
                      }
                    : null;
            const total_exchange = form.totalUnlimit == 1 ? 0 : totalExchange || 0;
            const total_unlimit = totalUnlimit;
            let goodsImg = null;
            if (form.goodsType == 2) {
                goodsImg = couponIconUrl;
            }
            if (form.goodsType == 3) {
                goodsImg = drawIconUrl;
            }
            const { code } = await request('pointsGoodsAdd', {
                ...rest,
                goodsImg,
                shopId: selectData?.shopId || skuSelect?.[0]?.shopId,
                limitConfig: {
                    type: 'per_buy_max_count',
                    value: radioVal.value == 1 ? 0 : limit || 0,
                    total_exchange,
                    total_unlimit
                },
                goodsList,
                couponList,
                luckDraw
            });
            if (code !== 0) {
                return;
            }
            ElMessage({
                type: 'success',
                message: '添加成功'
            });
            handleVisible();
            emit('handle-confirm');
        } else {
            unref(formRef).scrollToField(Object.keys(fields)?.[0]);
        }
    });
}, 500);
</script>

<style lang="scss">
.good_spec_template_dialog {
    max-width: 1000px;
    min-width: 900px;
    .el-input-number .el-input__inner {
        text-align: left;
    }
    .el-radio__input.is-checked + .el-radio__label {
        color: var(--el-table-text-color);
    }
    .custom-table-fit {
        width: 90%;
        max-width: 90%;
    }
    .custom-goods-name {
        display: inline-flex;
        align-items: center;
        width: 100%;
        &-span {
            display: -webkit-box;
            max-width: calc(100% - 45px);
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            overflow: hidden;
        }
    }
}
</style>
<style lang="scss" scoped>
.good_spec_template_dialog {
    .width-60 {
        width: 60px;
    }
    .custom-group {
        .radio-item {
            width: 100%;
            display: flex;
            :deep .el-radio {
                margin-right: 16px;
            }
        }
    }
    .good-name-input {
        width: 350px;
    }
    .custom-number-small {
        width: 80px;
        margin: 0 4px 0 4px;
    }
    .custom-number-small-s {
        width: 160px;
    }

    .custom-point-tag {
        margin-left: 5px;
        border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
        color: var(--el-disabled-text-color);
        background-color: var(--el-disabled-bg-color);
        border-color: var(--el-disabled-border-color);
        /* box-shadow: 0 0 0 1px var(--el-disabled-border-color) inset; */
    }
}
</style>
